package com.treasure.mall.zbqmallmanager.controller.live;

import com.treasure.mall.biz.base.UserDetails;
import com.treasure.mall.biz.dto.common.ChatMessageBodyDTO;
import com.treasure.mall.biz.dto.condition.*;
import com.treasure.mall.biz.dto.live.*;
import com.treasure.mall.biz.entity.live.*;
import com.treasure.mall.biz.entity.product.CategoryPO;
import com.treasure.mall.biz.entity.product.ProductPO;
import com.treasure.mall.biz.entity.user.UserPO;
import com.treasure.mall.biz.remote.live.TencentIMService;
import com.treasure.mall.biz.remote.live.dto.GeneralMessageDTO;
import com.treasure.mall.biz.remote.live.enums.MessageType;
import com.treasure.mall.biz.service.core.live.*;
import com.treasure.mall.biz.service.core.product.CategoryService;
import com.treasure.mall.biz.service.core.product.ProductService;
import com.treasure.mall.biz.service.core.user.UserService;
import com.treasure.mall.zbq.common.StringUtilsExt;
import com.treasure.mall.zbq.common.base.ApiResult;
import com.treasure.mall.zbq.common.constant.Constant;
import com.treasure.mall.zbq.common.ienum.auth.RoleEnum;
import com.treasure.mall.zbq.common.ienum.base.CodeDescEnumHelper;
import com.treasure.mall.zbq.common.ienum.live.LiveEnums;
import com.treasure.mall.zbq.common.ienum.product.ProductEnums;
import com.treasure.mall.zbqmallmanager.vo.FindUserVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * @author allan
 * @version 1.0.0
 * @date 2020/6/14
 */
@Controller
@RequestMapping("/live")
public class LiveController {
    @Autowired
    private LiveRoomService liveRoomService;
    @Autowired
    private ProductService productService;
    @Autowired
    private LiveSessionService liveSessionService;
    @Autowired
    private LiveDirectorService directorService;
    @Autowired
    private UserService userService;
    @Autowired
    private LiveRobotService liveRobotService;
    @Autowired
    private TencentIMService tencentIMService;
    @Autowired
    private LiveHistoryMessageService liveHistoryMessageService;
    @Autowired
    private LiveRoomVideoService liveRoomVideoService;
    @Autowired
    private LiveRoomUserService liveRoomUserService;
    @Autowired
    private LiveRoomImagesService liveRoomImagesService;
    @Autowired
    private CategoryService categoryService;

    @GetMapping("/list")
    public String list(
            @ModelAttribute("condition") LiveRoomSearchCondition condition,
            @RequestParam(required = false, defaultValue = "1") int pageIndex,
            @RequestParam(required = false, defaultValue = "1") int auditStatus,
            Model model
    ) {
        condition.setAuditStatus(auditStatus);
        Page<LiveRoomPO> orderPOS = liveRoomService.findAll(pageIndex, Constant.DEFAULT_PAGE_SIZE, condition);

        model.addAttribute("pageIndex", pageIndex);
        model.addAttribute("totalRecords", orderPOS.getTotalElements());
        model.addAttribute("totalPages", orderPOS.getTotalPages());
        model.addAttribute("rooms", orderPOS.getContent());

        return "live/live_room_list";
    }

    @GetMapping("/edit")
    public String edit(Long roomId, Model model) {
        LiveRoomPO liveRoomPO = liveRoomService.findById(roomId);
        model.addAttribute("room", liveRoomPO);

        return "live/live_edit";
    }

    @PostMapping("/edit/{roomId}")
    @ResponseBody
    public ApiResult edit(@PathVariable Long roomId, ApplyLiveDTO applyLiveDTO) {
        liveRoomService.edit(roomId, applyLiveDTO);
        return ApiResult.ok();
    }

    /**
     * 公告
     *
     * @param roomId
     * @param model
     * @return
     */
    @GetMapping("/edit/notice")
    public String editNotice(Long roomId, Model model) {
        LiveRoomPO liveRoomPO = liveRoomService.findById(roomId);
        model.addAttribute("room", liveRoomPO);
        return "live/live_edit_notice";
    }

    /**
     * 设置公告
     *
     * @param roomId
     * @param notice
     * @return
     */
    @PostMapping("/edit/notice/{roomId}")
    @ResponseBody
    public ApiResult editNotice(@PathVariable Long roomId, String notice) {
        if (StringUtils.isNotBlank(notice)) {
            liveRoomService.setNoticeContent(roomId, notice);
            //发送公告消息
            tencentIMService.sendMessage(GeneralMessageDTO.builder()
                    .roomId(roomId)
                    .message(StringUtilsExt.replaceEnterStr(notice))
                    .build(), MessageType.notice);
        }
        return ApiResult.ok();
    }

    /**
     * 启用或禁用公告
     *
     * @param roomId
     * @param enable
     * @return
     */
    @PostMapping("/edit/notice/enable/{roomId}")
    @ResponseBody
    public ApiResult enableNotice(@PathVariable Long roomId, boolean enable) {
        liveRoomService.enableNotice(roomId, enable);

        //关闭公告消息
        tencentIMService.sendMessage(GeneralMessageDTO.builder()
                .roomId(roomId)
                .build(), MessageType.closeNotice);

        return ApiResult.ok();
    }


    @PostMapping("/sort/{roomId}")
    @ResponseBody
    public ApiResult sort(@PathVariable Long roomId, int orderWeight) {
        liveRoomService.sort(roomId, orderWeight);

        return ApiResult.ok();
    }

    @GetMapping("/detail/products")
    public String detail(
            @RequestParam(required = false, defaultValue = "0") Long roomId,
            @RequestParam(required = false, defaultValue = "1") int pageIndex,
            @AuthenticationPrincipal UserDetails userDetails,
            Model model) {
        LiveRoomPO liveRoomPO;
        if (userDetails.getRoleType() == RoleEnum.MERCHANT) {
            //如果是商家，默认进入
            liveRoomPO = liveRoomService.findByMerchant(userDetails.getId());
            if (liveRoomPO == null) {
                return "redirect:error";
            }
        } else {
            liveRoomPO = liveRoomService.findById(roomId);
        }
        model.addAttribute("room", liveRoomPO);
        //商品
        ProductSearchCondition condition = new ProductSearchCondition();
        condition.setProductType(ProductEnums.ProductType.LIVE_BROADCAST.getCode());
        condition.setRoomId(roomId);

        Page<ProductPO> productPOS = productService.findAll(pageIndex, Constant.DEFAULT_PAGE_SIZE, condition);
        productService.processExclusiveUser(productPOS.getContent());
        model.addAttribute("pageIndex", pageIndex);
        model.addAttribute("totalRecords", productPOS.getTotalElements());
        model.addAttribute("totalPages", productPOS.getTotalPages());
        model.addAttribute("products", productPOS.getContent());

        return "live/live_detail_products";
    }

    @GetMapping("/detail/error")
    public String error() {
        return "live/error";
    }

    /**
     * 主播管理
     *
     * @return
     */
    @GetMapping("/detail/directors")
    public String directors(Long roomId, Model model) {
        model.addAttribute("room", liveRoomService.findById(roomId));
        model.addAttribute("directors", directorService.findByRoom(roomId));

        return "live/live_detail_director";
    }

    @PostMapping("/detail/directors/findUser")
    @ResponseBody
    public ApiResult findUser(String userKey) {
        UserSearchCondition searchCondition = new UserSearchCondition();
        searchCondition.setKeyword(userKey);
        Page<UserPO> userPOS = userService.findAll(1, 5, searchCondition);
        List<FindUserVO> userVOS = new ArrayList<>();
        userPOS.getContent().forEach(p -> userVOS.add(new FindUserVO(p)));

        return ApiResult.ok(userVOS);
    }

    @PostMapping("/detail/directors/add")
    @ResponseBody
    public ApiResult addDirector(DirectorSaveDTO saveDTO) {

        if (saveDTO.getUserId() == null) {
            return ApiResult.error("请选择要添加的主播");
        }


        directorService.save(saveDTO);

        return ApiResult.ok();
    }

    @PostMapping("/detail/directors/changeName")
    @ResponseBody
    public ApiResult changeDirectorName(Long directorId, String directorName) {
        directorService.modifyName(directorId, directorName);

        return ApiResult.ok();
    }

    @PostMapping("/detail/directors/remove")
    @ResponseBody
    public ApiResult removeDirector(Long directorId) {
        directorService.deleteById(directorId);

        return ApiResult.ok();
    }

    @GetMapping("/detail/sessions")
    public String sessions(Long roomId, @RequestParam(required = false, defaultValue = "1") int pageIndex, Model model) {
        model.addAttribute("room", liveRoomService.findById(roomId));
        LiveSessionCondition condition = new LiveSessionCondition(roomId);

        Page<LiveSessionPO> productPOS = liveSessionService.findAll(pageIndex, Constant.DEFAULT_PAGE_SIZE, condition);
        model.addAttribute("pageIndex", pageIndex);
        model.addAttribute("totalRecords", productPOS.getTotalElements());
        model.addAttribute("totalPages", productPOS.getTotalPages());
        model.addAttribute("sessions", productPOS.getContent());

        //直播中的场次
        Optional<LiveSessionPO> sessionPOOptional = productPOS.getContent().stream().filter(p -> p.getPlayStatus() == LiveEnums.PlayStatus.PAYING).findAny();
        if (sessionPOOptional.isPresent()) {
            LiveSessionPO liveSessionPO = sessionPOOptional.get();
            liveSessionPO.setStatisticsDTO(liveSessionService.getStatistics(liveSessionPO.getId()));
        }

        model.addAttribute("directors", directorService.findByRoom(roomId));

        return "live/live_detail_session";
    }

    @PostMapping("/detail/sessions/create")
    @ResponseBody
    public ApiResult createSession(LiveSessionCreateDTO createDTO, Long directorId) {
        LiveDirectorPO directorPO = directorService.findById(directorId);
        createDTO.setLiveDirector(directorPO);
        liveSessionService.create(createDTO);

        return ApiResult.ok();
    }

    @PostMapping("/detail/sessions/delete")
    @ResponseBody
    public ApiResult deleteSession(String sessionId) {
        liveSessionService.delete(sessionId);

        return ApiResult.ok();
    }

    @PostMapping("/detail/sessions/stop")
    @ResponseBody
    public ApiResult stopSession(String sessionId) {
        liveSessionService.stop(sessionId);
        LiveSessionPO po = liveSessionService.findById(sessionId);
        if (po != null) {
            liveRoomVideoService.resetPushed(po.getLiveRoomPO().getId());
            liveRoomImagesService.resetPushed(po.getLiveRoomPO().getId());
        }
        return ApiResult.ok();
    }

    @PostMapping("/stop/{roomId}")
    @ResponseBody
    public ApiResult stop(@PathVariable Long roomId) {
        liveSessionService.stopByRoom(roomId);
        liveRoomVideoService.resetPushed(roomId);
        liveRoomImagesService.resetPushed(roomId);
        return ApiResult.ok();
    }

    @PostMapping("/enableToggle/{roomId}")
    @ResponseBody
    public ApiResult enableToggle(@PathVariable Long roomId, boolean enable) {
        liveRoomService.enableToggle(roomId, enable);

        return ApiResult.ok();
    }

    @PostMapping("/setRewardRate/{roomId}")
    @ResponseBody
    public ApiResult setRewardRate(@PathVariable Long roomId, BigDecimal rate) {
        liveRoomService.setRewardRate(roomId, rate);

        return ApiResult.ok();
    }

    @PostMapping("/audit/{roomId}")
    @ResponseBody
    public ApiResult audit(@PathVariable Long roomId, int auditStatus, String remark) {
        liveRoomService.audit(roomId, CodeDescEnumHelper.getEnumTypeByCode(LiveEnums.AuditStatus.class, auditStatus), remark);

        return ApiResult.ok();
    }

    @PostMapping("/modifyPlatformType/{roomId}")
    @PreAuthorize("hasRole('ADMIN')")
    @ResponseBody
    public ApiResult modifyPlatformType(@PathVariable Long roomId, boolean platform) {
        liveRoomService.modifyPlatformType(roomId, platform);
        return ApiResult.ok();
    }


    @GetMapping("/edit/rec")
    public String editRecommend(Long roomId, Model model) {
        LiveRoomPO liveRoomPO = liveRoomService.findById(roomId);
        model.addAttribute("room", liveRoomPO);

        return "live/live_edit_recommend";
    }

    @PostMapping("/edit/rec")
    @ResponseBody
    public ApiResult editRecommend(LiveRecommendSaveDTO dto) {
        liveRoomService.modifyRecommend(dto);
        return ApiResult.ok();
    }

    /**
     * 开启或关闭机器人
     *
     * @param roomId
     * @param dto
     * @return
     */
    @PostMapping("/enableRobot/{roomId}")
    @ResponseBody
    public ApiResult enableRobot(@PathVariable Long roomId, LiveRobotConfigDTO dto) {
        dto.setLiveRoomId(roomId);
        if (dto.isEnable()) {
            liveRobotService.startAutoJoin(dto);
        } else {
            liveRobotService.stop(roomId);
        }
        return ApiResult.ok();
    }

    /**
     * 修改直播间观看人数
     *
     * @param roomId
     * @param num
     * @return
     */
    @PostMapping("/modifyMemberNum/{roomId}")
    @ResponseBody
    public ApiResult modifyMemberNum(@PathVariable Long roomId, @RequestParam Integer num) {
        tencentIMService.modifyMemberNum(roomId, num);
        return ApiResult.ok();
    }


    /**
     * 发布直播间聊天消息
     *
     * @param roomId
     * @return
     */
    @PostMapping("/sendGeneralMessage/{roomId}")
    @PreAuthorize("hasRole('ADMIN')")
    @ResponseBody
    public ApiResult sendGeneralMessage(@PathVariable Long roomId, String nick, String levelName, int level, String message, @RequestParam(required = false, defaultValue = "5") Integer type) {

        if (type == null) {
            return ApiResult.ok();
        }
        MessageType messageType = CodeDescEnumHelper.getEnumTypeByCode(MessageType.class, type);
        if (messageType == null) {
            return ApiResult.ok();
        }
        LiveRoomPO roomPO = liveRoomService.findById(roomId);
        if (roomPO == null || StringUtils.isEmpty(roomPO.getSessionId())) {
            return ApiResult.ok();
        }


        // 后台模拟发送的消息，也进聊天记录
        ChatMessageBodyDTO dto = new ChatMessageBodyDTO();
        dto.setType(messageType.getDesc());
        dto.setName(nick);
        dto.setGroupId(roomPO.toStreamName());
        dto.setMessage(message);
        dto.setTime(LocalDateTime.now());
        dto.setLevel(new LiveMessageUserLevel(level, levelName));
        liveHistoryMessageService.save(roomPO.getSessionId(), null, dto);


        tencentIMService.sendMessage(GeneralMessageDTO.builder()
                .level(new LiveMessageUserLevel(level, levelName))
                .roomId(roomId)
                .nick(nick)
                .message(message)
                .build(), messageType);
        return ApiResult.ok();
    }

    @GetMapping("/sendGeneralMessage")
    public String editMessage(Long roomId, Model model) {
        LiveRoomPO liveRoomPO = liveRoomService.findById(roomId);
        model.addAttribute("room", liveRoomPO);
        return "live/live_send_message";
    }

    /**
     * 直播间视频列表
     *
     * @param roomId
     * @param pageIndex
     * @param model
     * @return
     */
    @GetMapping("/detail/videos")
    public String videos(
            @RequestParam(required = false, defaultValue = "0") Long roomId,
            @RequestParam(required = false, defaultValue = "1") int pageIndex,
            Model model
    ) {
        model.addAttribute("room", liveRoomService.findById(roomId));
        LiveRoomVideoSearchCondition condition = new LiveRoomVideoSearchCondition();
        condition.setRoomId(roomId);
        Page<LiveRoomVideoPO> pos = liveRoomVideoService.findAll(pageIndex, Constant.DEFAULT_PAGE_SIZE, condition);
        model.addAttribute("pageIndex", pageIndex);
        model.addAttribute("totalRecords", pos.getTotalElements());
        model.addAttribute("totalPages", pos.getTotalPages());
        model.addAttribute("list", pos.getContent());
        return "live/live_detail_videos";
    }

    /**
     * 添加直播间视频
     *
     * @param dto
     * @return
     */
    @PostMapping("/detail/videos/sendVideoMessage")
    @ResponseBody
    public ApiResult sendVideoMessage(LiveRoomVideoSaveDTO dto) {
        liveRoomVideoService.save(dto);
        return ApiResult.ok();
    }

    /**
     * 删除直播间视频
     *
     * @param id
     * @return
     */
    @GetMapping("/detail/videos/delete")
    @ResponseBody
    public ApiResult deleteVideo(@RequestParam Long id) {
        LiveRoomVideoPO po = liveRoomVideoService.findById(id);
        if (po != null) {
            liveRoomVideoService.delete(id);
            //发送关闭视频消息
            tencentIMService.sendMessage(GeneralMessageDTO.builder()
                    .roomId(po.getRoomId())
                    .build(), MessageType.closeVideo);

            return ApiResult.ok();
        } else {
            return ApiResult.error("视频不存在或已删除");
        }
    }

    /**
     * 关闭正在播放的视频
     *
     * @param id 视频ID
     * @return
     */
    @GetMapping("/detail/videos/close")
    @ResponseBody
    public ApiResult closeVideo(@RequestParam Long id) {
        liveRoomVideoService.close(id);
        return ApiResult.ok();
    }


    /**
     * 推送直播间视频
     *
     * @param id
     * @return
     */
    @GetMapping("/detail/videos/push")
    @ResponseBody
    public ApiResult pushVideo(@RequestParam Long id) {
        LiveRoomVideoPO po = liveRoomVideoService.findById(id);
        if (po != null) {
            liveRoomVideoService.resetPushed(po.getRoomId());
        }
        liveRoomVideoService.push(id);
        return ApiResult.ok();
    }

    /**
     * 直播用户列表
     *
     * @param condition
     * @param roomId
     * @param pageIndex
     * @param model
     * @return
     */
    @GetMapping("/detail/users")
    @PreAuthorize("hasRole('ADMIN')")
    public String videos(
            @ModelAttribute("condition") BaseSearchCondition condition,
            @RequestParam(required = false, defaultValue = "0") Long roomId,
            @RequestParam(required = false, defaultValue = "1") int pageIndex,
            @RequestParam(required = false, defaultValue = "0") int showOnline,
            Model model
    ) {
        LiveRoomPO roomPO = liveRoomService.findById(roomId);
        model.addAttribute("room", roomPO);
        model.addAttribute("showOnline", showOnline);
        if (StringUtils.isEmpty(condition.getKeyword()) && StringUtils.isNotBlank(roomPO.getSessionId())) {
            condition.setKeyword(roomPO.getSessionId());
        }

        if (StringUtils.isEmpty(condition.getKeyword())) {
            model.addAttribute("pageIndex", 1);
            model.addAttribute("totalRecords", 0);
            model.addAttribute("totalPages", 0);
            model.addAttribute("list", new ArrayList<>());
        } else {
            Page<LiveRoomUserPO> pos = liveRoomUserService.findAll(pageIndex, Constant.DEFAULT_PAGE_SIZE, condition);
            model.addAttribute("pageIndex", pageIndex);
            model.addAttribute("totalRecords", pos.getTotalElements());
            model.addAttribute("totalPages", pos.getTotalPages());
            model.addAttribute("list", pos.getContent());
        }
        return "live/live_detail_users";
    }

    /**
     * 设置禁言
     *
     * @param id
     * @param forbid
     * @return
     */
    @GetMapping("/detail/users/forbid")
    @PreAuthorize("hasRole('ADMIN')")
    @ResponseBody
    public ApiResult setForbid(@RequestParam Long id, boolean forbid) {
        boolean b = liveRoomUserService.setForbid(id, forbid);
        if (b) {
            return ApiResult.ok();
        }
        return ApiResult.error("禁言失败");
    }

    /**
     * 设置佣金抽成比例
     *
     * @param roomId
     * @param model
     * @return
     */
    @GetMapping("/rate/edit")
    @PreAuthorize("hasRole('ADMIN')")
    public String editRate(Long roomId, Model model) {
        LiveRoomPO po = liveRoomService.findById(roomId);
        Long catId = po.getMerchant().getData().getMainCategory().getCatId();
        BigDecimal rebateRateOne = po.getRebateRateOne();
        BigDecimal rebateRateTwo = po.getRebateRateTwo();
        BigDecimal commissionRate = po.getRewardRate();
        CategoryPO categoryPO = categoryService.getRootCategory(catId);
        if (po.getRebateRateOne() == null) {
            rebateRateOne = categoryPO.getRebateRateOne();
        }
        if (po.getRebateRateTwo() == null) {
            rebateRateTwo = categoryPO.getRebateRateTwo();
        }
        if (po.getRewardRate() == null) {
            commissionRate = categoryPO.getCommissionRate();
        }
        model.addAttribute("roomId", roomId);
        model.addAttribute("commissionRate", commissionRate);
        model.addAttribute("rebateRateOne", rebateRateOne);
        model.addAttribute("rebateRateTwo", rebateRateTwo);
        model.addAttribute("platformRemain", BigDecimal.valueOf(100).subtract(rebateRateOne).subtract(rebateRateTwo).abs());
        return "live/live_edit_rate";
    }

    /**
     * 保存佣金抽成比例
     *
     * @param roomId
     * @param commissionRate
     * @param rebateRateOne
     * @param rebateRateTwo
     * @return
     */
    @PostMapping("/rate/edit/{roomId}")
    @ResponseBody
    @PreAuthorize("hasRole('ADMIN')")
    public ApiResult editRate(@PathVariable Long roomId, BigDecimal commissionRate, BigDecimal rebateRateOne, BigDecimal rebateRateTwo) {
        if (commissionRate == null) {
            return ApiResult.error("请输入抽成比例");
        }
        liveRoomService.setRewardRate(roomId, commissionRate, rebateRateOne, rebateRateTwo);
        return ApiResult.ok();
    }


}
